package cn.xchats.rpc.common.core;

import cn.xchats.rpc.common.dto.RequestDto;
import cn.xchats.rpc.common.dto.ResponseDto;
import lombok.Getter;
import lombok.Setter;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
 *
 *@author teddy
 *@date 2018/6/28
 */
@SuppressWarnings("all")
public class TcpFuture {

    public final static ConcurrentHashMap<Long, TcpFuture> tcpFutureMap = new ConcurrentHashMap<Long, TcpFuture>();
    final Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    @Getter
    @Setter
    private ResponseDto response;//future返回的值

    @Getter
    @Setter
    private int timeoutState = 0;// -1 超时
    private static final int timeoutStateDefault = -1;//超时
    private static final long timeoutDefault = 5*1000;//默认的超时时间
    private static long timeout = timeoutDefault;//超时时间
    private static TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;//超时时间的单位(秒)
    private long startTime = System.currentTimeMillis();//

    public TcpFuture(RequestDto request) {
        tcpFutureMap.put(request.getId(), this);
    }

    /**
     * 主线程获取数据，首先要等待结果
     */
    public <T extends ResponseDto> T get() {
        lock.lock();
        try {
            //dubbo里的同步变异步？？？
            while (!done()) //response为空
                condition.await();//等待唤醒  唤醒之前会卡在这里
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return (T) response;
    }

    /**
     * 主线程获取数据，首先要等待结果 (超时)
     */
    public <T extends ResponseDto> T getTimeout() {
        lock.lock();
        try {
            //dubbo里的同步变异步
            while (!done()) { //response为空
                condition.await(timeout, timeoutUnit);//等待唤醒  唤醒之前会卡在这里
                if (System.currentTimeMillis() - startTime > timeout) {
                    System.out.println("RPC > > > > > > > > > > > > > > > 请求超时");
                    //解决超时的缓存问题
                    timeoutState = timeoutStateDefault;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return (T) response;
    }

    /**
     * 接收返回数据
     */
    public static void recive(ResponseDto response) {
        TcpFuture tcpFuture = tcpFutureMap.get(response.getId());
        if (null != tcpFuture) {
            Lock lock = tcpFuture.lock;
            Condition condition = tcpFuture.condition;

            lock.lock();
            try {
                tcpFuture.setResponse(response);
                condition.signal();//唤醒get方法，让其返回response
                //清空当前实例的map
                tcpFutureMap.remove(response.getId());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 是否接受到数据
     */
    private boolean done() {
        if (null != response)
            return true;
        return false;
    }

}
